#include "NodeInPort.h"
#include "AbstractShapeItem.h"
#include "NodeItem.h"
#include "DiagramScene.h"
#include "AbstractMappingWindow.h"
#include "LineItem.h"
#include "xInMappingPort.h"
#include "AbstractManager.h"
#include "NodeOutPort.h"
#include "xMappingNode.h"

#include <QtGui/QPainter>
#include <QtGui/QGraphicsSceneMouseEvent>
#include <QtGui/QGraphicsScene>
#include <QtGui/QPen>

namespace {
	const static int TYPE_BLOCK_RIGHT_PADDING = 4;
	const static int TYPE_BLOCK_LEFT_PADDING = 4;
	const static int LEFT_PADDING = 14;
	const static int TOP_PADDING = 0;
}

NodeInPort::NodeInPort(xInMappingPort* inport, AbstractShapeItem* parent)
	:NodePort(parent)
{
	this->_inport = inport;
	this->_parent = parent;

	// inport為NULL代表他的parent是一個NodeSubShape node，該node的inport只是為了顯示用
	if ( inport!= NULL )
	{
		this->_name = this->_inport->getName();
		this->setPortInitVisible();
	}

	this->_portIOType = NodePort::INPORT;
	this->setBrush(QBrush("#333333"));
	_x = 0 - NodePort::RADIUS;
}

NodeInPort::~NodeInPort(void)
{
}

void NodeInPort::paint( QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
	// 假如是 GateItem 的 inport，則改畫成下面的形狀
	if ( this->_parent->nodeType() == AbstractShapeItem::GATE_NODE) {

		painter->setBrush(QBrush(QColor("#333333")));
		painter->setPen(QPen(QColor("#FFFFFF")));

		QImage outputImage(":/resource/outport.png");
		outputImage = outputImage.mirrored( true, false );
		painter->drawEllipse( this->_x, this->_y, NodePort::GATE_RADIUS*2, NodePort::GATE_RADIUS*2 );
		painter->drawImage( this->_x + GATE_RADIUS / 2, this->_y + GATE_RADIUS / 2, outputImage );

		return;
	}

	// 畫 Item type block 跟 type 名稱
	QFont sansFont("Helvetica", 8);
	QFontMetrics fontMetrics(sansFont);
	int typeBlockWidth = fontMetrics.width(this->_inport->getType().c_str()) + TYPE_BLOCK_LEFT_PADDING + TYPE_BLOCK_RIGHT_PADDING;
	int typeBlockHeight = fontMetrics.height();

	painter->setPen(QPen(Qt::NoPen));
	painter->setBrush(QBrush(QColor("#575757")));
	painter->drawRoundedRect( this->_x + LEFT_PADDING, this->_y + TOP_PADDING, typeBlockWidth, typeBlockHeight, 0, 0 );

	painter->setPen(QPen(QColor("#FFFFFF")));
	painter->setFont(sansFont);
	painter->drawText( this->_x + LEFT_PADDING, this->_y + TOP_PADDING, typeBlockWidth, typeBlockHeight, Qt::AlignCenter, trf(this->_inport->getType()).c_str());

	painter->setBrush(this->brush());
	painter->setPen(QPen(Qt::NoPen));
	
	painter->drawEllipse( this->_x, this->_y, NodePort::RADIUS*2, NodePort::RADIUS*2);

	if ( !this->_portLineList.empty() )
	{
		QPointF center( this->_x+ NodePort::RADIUS, this->_y+ NodePort::RADIUS );
		painter->setBrush(QBrush(Qt::white));
		painter->drawEllipse(center, 3, 3);
	}

	// 繪製port name
	painter->setFont(sansFont);
	painter->setPen(QPen("#DDDDDD"));
	painter->drawText( this->_x + 20 + typeBlockWidth, this->_y,80,20, Qt::AlignLeft, trf(_name).c_str());
}

QRectF NodeInPort::boundingRect() const
{
	return QRectF( this->_x, this->_y, 85, 20);
}

int NodeInPort::getClass()
{
	assert(this->_inport);
	return _inport->getClass();
}

int NodeInPort::getCategory()
{
	assert(this->_inport);
	return _inport->getCategory();
}

void NodeInPort::mouseReleaseEvent( QGraphicsSceneMouseEvent* event)
{
	DiagramScene* scene = this->_parent->getManager()->getMappingDialog()->currentScene();

	if ( event->button() == Qt::LeftButton ) {
		AbstractManager* manager = this->_parent->getManager();
		NodePort* releasePort = manager->getCollidePort(event->scenePos());	

		// 當滑鼠放開時有port且為合法連結時才產生link
		if ( releasePort!=NULL && manager->verifyLink(this, releasePort)) {
			NodeOutPort* outport = (NodeOutPort*)releasePort;
			outport->setPen(QPen(QBrush(Qt::white), 3));
			LineItem* newLine = manager->createLine(this, outport);
			scene->addItem(newLine);

			// 假如目的 node outport的個數是可變動的，則當新的link產生時要增加一個新port
			if (!outport->getParent()->getMappingNode()->getNodeTypePtr()->getOutportFixed()) {
				outport->getParent()->addOutPort();
			}
			if (!this->getParent()->getMappingNode()->getNodeTypePtr()->getInportFixed()) {
				this->getParent()->addInPort();
			}
		}
	} 

	this->scene()->removeItem(_line);
	_line = NULL;
}

xInMappingPort* NodeInPort::getInport()
{
	return this->_inport;
}

QString NodeInPort::getPortValue()
{
	QString portValue(_inport->getDefaultValue().c_str());
	return portValue;
}
